// ==================== src/metadata.rs ====================
//! 元数据定义
//!
//! 本模块定义了Nacos系统中的所有核心数据结构和元数据类型，
//! 包括服务实例、配置项、集群节点等关键概念。
//!
//! # 核心数据结构
//!
//! ## 服务实例（ServiceInstance）
//! 表示一个可被发现和调用的服务实例，包含以下关键信息：
//! - 实例标识：唯一标识服务实例
//! - 网络信息：IP地址和端口
//! - 状态信息：健康状态、权重、是否启用等
//! - 元数据：扩展的配置信息
//! - 时间信息：创建、更新、心跳时间
//!
//! ## 配置项（ConfigItem）
//! 表示一个配置中心的配置条目，包含：
//! - 配置标识：data_id、group、namespace
//! - 配置内容：实际的配置数据
//! - 版本信息：版本号和MD5校验
//! - 元数据：创建者、描述等
//!
//! ## 集群节点（ClusterNode）
//! 表示集群中的一个节点，包含：
//! - 节点标识：节点ID和地址
//! - 状态信息：运行状态、角色、心跳时间
//! - 元数据：扩展的节点信息
//!
//! # 使用场景
//! - 服务注册与发现：使用ServiceInstance
//! - 配置管理：使用ConfigItem
//! - 集群管理：使用ClusterNode
//! - 健康检查：使用HealthCheckResult
//!
//! # 序列化支持
//! 所有数据结构都支持JSON序列化，便于网络传输和持久化存储。

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use chrono::{DateTime, Utc};
use uuid::Uuid;

/// 服务实例
///
/// 表示Nacos系统中的一个服务实例，包含完整的实例信息和状态。
/// 用于服务注册、发现、健康检查等场景。
///
/// # 字段说明
///
/// ## 标识信息
/// - `instance_id`: 实例唯一标识符，使用UUID生成
/// - `service_name`: 服务名称，用于服务发现
/// - `group_name`: 服务分组名称，用于服务隔离
/// - `namespace`: 命名空间，用于环境隔离
///
/// ## 网络信息
/// - `ip`: 服务实例的IP地址
/// - `port`: 服务实例的端口号
///
/// ## 权重和状态
/// - `weight`: 实例权重，用于负载均衡算法
/// - `healthy`: 健康状态，由健康检查决定
/// - `enabled`: 启用状态，可手动控制
/// - `ephemeral`: 是否为临时实例，临时实例在客户端断开后自动注销
///
/// ## 扩展信息
/// - `cluster_name`: 集群名称，用于集群级别的服务管理
/// - `metadata`: 扩展元数据，可存储自定义配置
///
/// ## 时间戳
/// - `create_time`: 实例创建时间
/// - `update_time`: 实例最后更新时间
/// - `last_heartbeat_time`: 最后心跳时间，用于判断实例是否存活
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ServiceInstance {
    /// 实例ID
    pub instance_id: String,
    /// 服务名
    pub service_name: String,
    /// 分组名
    pub group_name: String,
    /// 命名空间
    pub namespace: String,
    /// IP地址
    pub ip: String,
    /// 端口
    pub port: u16,
    /// 权重
    pub weight: f64,
    /// 是否健康
    pub healthy: bool,
    /// 是否启用
    pub enabled: bool,
    /// 是否临时实例
    pub ephemeral: bool,
    /// 集群名
    pub cluster_name: String,
    /// 元数据
    pub metadata: HashMap<String, String>,
    /// 创建时间
    pub create_time: DateTime<Utc>,
    /// 更新时间
    pub update_time: DateTime<Utc>,
    /// 最后心跳时间
    pub last_heartbeat_time: DateTime<Utc>,
}

impl ServiceInstance {
    /// 创建新的服务实例
    ///
    /// # 参数
    /// - `service_name`: 服务名称，用于服务发现
    /// - `group_name`: 服务分组名称，用于服务隔离
    /// - `ip`: 服务实例的IP地址
    /// - `port`: 服务实例的端口号
    ///
    /// # 返回值
    /// - `ServiceInstance`: 新创建的服务实例，包含默认配置
    ///
    /// # 默认值
    /// - `instance_id`: 使用UUID4生成唯一标识
    /// - `namespace`: "public"（默认命名空间）
    /// - `weight`: 1.0（默认权重）
    /// - `healthy`: true（默认健康）
    /// - `enabled`: true（默认启用）
    /// - `ephemeral`: true（默认临时实例）
    /// - `cluster_name`: "DEFAULT"（默认集群）
    /// - `metadata`: 空HashMap（无元数据）
    /// - 所有时间戳：当前UTC时间
    ///
    /// # 示例
    /// ```
    /// let instance = ServiceInstance::new(
    ///     "user-service".to_string(),
    ///     "production".to_string(),
    ///     "192.168.1.100".to_string(),
    ///     8080,
    /// );
    /// ```
    pub fn new(
        service_name: String,
        group_name: String,
        ip: String,
        port: u16,
    ) -> Self {
        let now = Utc::now();
        Self {
            instance_id: Uuid::new_v4().to_string(),
            service_name,
            group_name,
            namespace: "public".to_string(),
            ip,
            port,
            weight: 1.0,
            healthy: true,
            enabled: true,
            ephemeral: true,
            cluster_name: "DEFAULT".to_string(),
            metadata: HashMap::new(),
            create_time: now,
            update_time: now,
            last_heartbeat_time: now,
        }
    }
    
    /// 获取实例的唯一标识
    ///
    /// # 返回值
    /// - `String`: 实例的唯一标识符，格式为"namespace#group_name#service_name#instance_id"
    ///
    /// # 使用场景
    /// - 用作存储系统的键
    /// - 用作缓存的键
    /// - 用作日志标识
    ///
    /// # 示例
    /// ```
    /// let key = instance.get_key();
    /// // 结果为: "public#production#user-service#123e4567-e89b-12d3-a456-426614174000"
    /// ```
    pub fn get_key(&self) -> String {
        format!("{}#{}#{}#{}" , self.namespace, self.group_name, self.service_name, self.instance_id)
    }
}

/// 配置项
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ConfigItem {
    /// 数据ID
    pub data_id: String,
    /// 分组
    pub group: String,
    /// 命名空间
    pub namespace: String,
    /// 配置内容
    pub content: String,
    /// 配置类型
    pub config_type: ConfigType,
    /// MD5值
    pub md5: String,
    /// 版本号
    pub version: u64,
    /// 创建时间
    pub create_time: DateTime<Utc>,
    /// 更新时间
    pub update_time: DateTime<Utc>,
    /// 创建者
    pub creator: Option<String>,
    /// 描述
    pub description: Option<String>,
}

impl ConfigItem {
    /// 创建新的配置项
    pub fn new(data_id: String, group: String, content: String) -> Self {
        let now = Utc::now();
        Self {
            data_id,
            group,
            namespace: "public".to_string(),
            content,
            config_type: ConfigType::Text,
            md5: String::new(),
            version: 1,
            create_time: now,
            update_time: now,
            creator: None,
            description: None,
        }
    }
    
    /// 获取配置的唯一标识
    pub fn get_key(&self) -> String {
        format!("{}#{}#{}", self.namespace, self.group, self.data_id)
    }
}

/// 配置类型
///
/// 定义配置项的不同格式类型，用于标识配置内容的格式和处理方式。
///
/// # 支持的格式
/// - `Text`: 纯文本格式
/// - `Json`: JSON格式配置
/// - `Xml`: XML格式配置
/// - `Yaml`: YAML格式配置
/// - `Properties`: Java properties格式
/// - `Html`: HTML格式配置
///
/// # 使用场景
/// - 客户端解析：根据类型选择合适的解析器
/// - 语法高亮：在配置中心界面显示
/// - 验证规则：根据类型应用不同的验证规则
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ConfigType {
    Text,
    Json,
    Xml,
    Yaml,
    Properties,
    Html,
}

/// 集群节点
///
/// 表示Nacos集群中的一个节点，包含节点的身份、状态、角色等关键信息。
/// 用于集群管理、节点发现、故障检测等场景。
///
/// # 字段说明
///
/// ## 节点标识
/// - `node_id`: 节点唯一标识符
/// - `ip`: 节点IP地址
/// - `port`: 节点端口号
///
/// ## 状态信息
/// - `state`: 节点运行状态（运行中、停止、故障等）
/// - `role`: 节点角色（领导者、跟随者、候选者）
/// - `last_heartbeat`: 最后心跳时间，用于故障检测
/// - `join_time`: 节点加入集群的时间
///
/// ## 扩展信息
/// - `metadata`: 扩展元数据，可存储节点版本、负载等信息
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
pub struct ClusterNode {
    /// 节点ID
    pub node_id: String,
    /// IP地址
    pub ip: String,
    /// 节点端口
    pub port: u16,
    /// 节点状态
    pub state: NodeState,
    /// 节点角色
    pub role: NodeRole,
    /// 最后心跳时间
    pub last_heartbeat: DateTime<Utc>,
    /// 加入集群时间
    pub join_time: DateTime<Utc>,
    /// 元数据
    pub metadata: HashMap<String, String>,
}

impl ClusterNode {
    /// 获取节点地址
    ///
    /// # 返回值
    /// - `String`: 节点的网络地址，格式为"ip:port"
    ///
    /// # 示例
    /// ```
    /// let addr = node.get_addr();
    /// // 结果为: "192.168.1.100:8848"
    /// ```
    pub fn get_addr(&self) -> String {
        format!("{}:{}", self.ip, self.port)
    }
}

/// 节点状态
///
/// 表示集群节点的运行状态，用于故障检测和集群管理。
///
/// # 状态说明
/// - `Running`: 节点正常运行，可以提供服务
/// - `Stopped`: 节点已停止，不再提供服务
/// - `Failed`: 节点发生故障，需要人工干预
/// - `Left`: 节点已主动离开集群
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
pub enum NodeState {
    /// 运行中
    #[default]
    Running,
    /// 停止
    Stopped,
    /// 故障
    Failed,
    /// 离开集群
    Left,
}

/// 节点角色
///
/// 表示节点在集群中的角色，主要用于Raft等分布式一致性算法。
///
/// # 角色说明
/// - `Leader`: 领导者，负责处理客户端请求和日志复制
/// - `Follower`: 跟随者，被动接收领导者的日志复制
/// - `Candidate`: 候选者，选举过程中的临时角色
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
pub enum NodeRole {
    /// 领导者
    Leader,
    /// 跟随者
    #[default]
    Follower,
    /// 候选者
    Candidate,
}

/// 健康检查结果
///
/// 表示服务实例健康检查的结果，用于服务发现和健康监控。
///
/// # 字段说明
/// - `instance_id`: 被检查的实例ID
/// - `healthy`: 健康检查结果，true表示健康，false表示不健康
/// - `check_time`: 检查执行的时间戳
/// - `error_message`: 检查失败时的错误信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthCheckResult {
    /// 实例ID
    pub instance_id: String,
    /// 是否健康
    pub healthy: bool,
    /// 检查时间
    pub check_time: DateTime<Utc>,
    /// 错误信息
    pub error_message: Option<String>,
}